package com.zzw.springboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzw.springboot.bean.SysRole;
import com.zzw.springboot.bean.SysRoleDept;
import com.zzw.springboot.bean.SysRoleMenu;
import com.zzw.springboot.mapper.SysRoleDeptMapper;
import com.zzw.springboot.mapper.SysRoleMapper;
import com.zzw.springboot.mapper.SysRoleMenuMapper;
import com.zzw.springboot.mapper.SysUserRoleMapper;
import com.zzw.springboot.service.SysRoleService;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 角色服务实现类
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysRoleMenuMapper roleMenuMapper;

    @Autowired
    private SysRoleDeptMapper roleDeptMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Override
    public SysRole selectRoleById(Integer roleId) {
        return roleMapper.selectRoleById(roleId);
    }

    @Override
    public List<SysRole> selectRolesByUserId(Integer userId) {
        return roleMapper.selectRolesByUserId(userId);
    }

    @Override
    public boolean checkRoleNameUnique(SysRole role) {
        Integer roleId = role.getId() == null ? 0 : role.getId();
        SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName(), roleId);
        return info == null;
    }

    @Override
    public boolean checkRoleCodeUnique(SysRole role) {
        Integer roleId = role.getId() == null ? 0 : role.getId();
        SysRole info = roleMapper.checkRoleCodeUnique(role.getRoleCode(), roleId);
        return info == null;
    }

    @Override
    @Transactional
    public boolean insertRole(SysRole role) {
        // 设置创建时间
        role.setCreateTime(new Date());
        // 新增角色信息
        int rows = roleMapper.insert(role);
        // 新增角色菜单关联
        insertRoleMenu(role);
        return rows > 0;
    }

    @Override
    @Transactional
    public boolean updateRole(SysRole role) {
        // 设置更新时间
        role.setUpdateTime(new Date());
        // 修改角色信息
        int rows = roleMapper.updateById(role);
        // 删除角色菜单关联
        roleMenuMapper.deleteRoleMenuByRoleId(role.getId());
        // 新增角色菜单关联
        insertRoleMenu(role);
        return rows > 0;
    }

    @Override
    public boolean updateRoleStatus(SysRole role) {
        // 设置更新时间
        role.setUpdateTime(new Date());
        return updateById(role);
    }

    @Override
    @Transactional
    public boolean deleteRoleByIds(Integer[] roleIds) {
        for (Integer roleId : roleIds) {
            checkRoleAllowed(roleId);
            checkRoleDataScope(roleId);
        }
        // 逻辑删除角色
        List<SysRole> roles = new ArrayList<>();
        for (Integer roleId : roleIds) {
            SysRole role = new SysRole();
            role.setId(roleId);
            role.setIsDeleted(1);
            role.setUpdateTime(new Date());
            roles.add(role);
        }
        return updateBatchById(roles);
    }

    /**
     * 检查角色是否允许操作
     */
    private void checkRoleAllowed(Integer roleId) {
        // 这里可以进行一些检查，例如不允许操作超级管理员角色
        if (roleId == 1) {
            throw new RuntimeException("不允许操作超级管理员角色");
        }
    }

    /**
     * 检查角色是否有数据权限
     */
    private void checkRoleDataScope(Integer roleId) {
        // 判断是否有用户使用该角色
        int count = userRoleMapper.countUserByRoleId(roleId);
        if (count > 0) {
            throw new RuntimeException("角色已分配给用户，不能删除");
        }
    }

    @Override
    @Transactional
    public boolean deleteRoleById(Integer roleId) {
        checkRoleAllowed(roleId);
        checkRoleDataScope(roleId);

        // 逻辑删除角色
        SysRole role = new SysRole();
        role.setId(roleId);
        role.setIsDeleted(1);
        role.setUpdateTime(new Date());

        return updateById(role);
    }

    @Override
    @Transactional
    public boolean authDataScope(SysRole role) {
        // 更新角色信息
        role.setUpdateTime(new Date());
        roleMapper.updateById(role);

        // 删除角色部门关联
        roleDeptMapper.deleteRoleDeptByRoleId(role.getId());

        // 添加角色部门关联
        if ("2".equals(role.getDataScope()) && role.getDeptIds() != null && !role.getDeptIds().isEmpty()) {
            List<SysRoleDept> roleDeptList = new ArrayList<>();
            for (Integer deptId : role.getDeptIds()) {
                SysRoleDept rd = new SysRoleDept();
                rd.setRoleId(role.getId());
                rd.setDeptId(deptId);
                rd.setCreateBy(role.getUpdateBy());
                rd.setCreateTime(new Date());
                roleDeptList.add(rd);
            }
            if (!roleDeptList.isEmpty()) {
                roleDeptMapper.batchInsert(roleDeptList);
            }
        }

        return true;
    }

    /**
     * 新增角色菜单关联
     */
    private void insertRoleMenu(SysRole role) {
        if (role.getMenuIds() != null && !role.getMenuIds().isEmpty()) {
            List<SysRoleMenu> roleMenuList = new ArrayList<>();
            for (Integer menuId : role.getMenuIds()) {
                SysRoleMenu rm = new SysRoleMenu();
                rm.setRoleId(role.getId());
                rm.setMenuId(menuId);
                rm.setCreateBy(role.getCreateBy());
                rm.setCreateTime(new Date());
                roleMenuList.add(rm);
            }
            if (!roleMenuList.isEmpty()) {
                roleMenuMapper.batchInsert(roleMenuList);
            }
        }
    }

    @Override
    public void exportRole(HttpServletResponse response, List<Integer> roleIds) throws IOException {
        try (Workbook workbook = new XSSFWorkbook()) {
            // 创建工作表
            Sheet sheet = workbook.createSheet("角色数据");
            
            // 创建表头
            Row headerRow = sheet.createRow(0);
            String[] headers = {"角色编号", "角色名称", "角色编码", "显示顺序", "状态", "描述", "创建时间"};
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
            }
            
            // 查询数据
            List<SysRole> roleList;
            if (roleIds != null && !roleIds.isEmpty()) {
                roleList = roleMapper.selectBatchIds(roleIds);
            } else {
                LambdaQueryWrapper<SysRole> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(SysRole::getIsDeleted, 0);
                roleList = list(queryWrapper);
            }
            
            // 填充数据
            int rowIndex = 1;
            for (SysRole role : roleList) {
                Row dataRow = sheet.createRow(rowIndex++);
                dataRow.createCell(0).setCellValue(role.getId());
                dataRow.createCell(1).setCellValue(role.getRoleName());
                dataRow.createCell(2).setCellValue(role.getRoleCode());
                dataRow.createCell(3).setCellValue(role.getSort());
                dataRow.createCell(4).setCellValue(role.getStatus() == 1 ? "正常" : "停用");
                dataRow.createCell(5).setCellValue(role.getDescription());
                dataRow.createCell(6).setCellValue(role.getCreateTime() != null ? role.getCreateTime().toString() : "");
            }
            
            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("角色数据", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            
            // 写入响应输出流
            OutputStream os = response.getOutputStream();
            workbook.write(os);
            os.flush();
        }
    }
}
